package com.dong.redis;

import com.dong.common.CommonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Component
public class RedisUtil {

    private Logger logger = LoggerFactory.getLogger(RedisUtil.class);
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 设置缓存
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
        } catch (Exception e) {
            logger.error("redis set error!", e);
            return false;
        }
        return true;
    }

    /**
     * 获取缓存
     *
     * @param key
     * @return
     */
    public Object get(String key) {
        Object value = null;
        try {
            value = redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            logger.error("redis get error!", e);
        }
        return value;
    }

    public Integer getInteger(String key) {
        try {
            return new Integer(Integer.parseInt(get(key).toString()));
        } catch (Exception e) {
            logger.error("redis getInteger error!", e);
            return null;
        }
    }

    public Map<String, Object> getMap(String key) {
        try {
            return (Map<String, Object>) get(key);
        } catch (Exception e) {
            logger.error("redis getMap error!", e);
            return null;
        }
    }

    public List<Object> getList(String key) {
        try {
            return (List<Object>) get(key);
        } catch (Exception e) {
            logger.error("redis getList error!", e);
            return null;
        }
    }

    /**
     * 删除缓存
     *
     * @param key
     * @return
     */
    public boolean delete(String key) {
        boolean result = false;
        try {
            result = redisTemplate.delete(key);
        } catch (Exception e) {
            logger.error("redis delete error!", e);
        }
        return result;
    }

    /**
     * 检查缓存是否存在
     *
     * @param key
     * @return
     */
    public boolean contains(String key) {
        boolean result = false;
        try {
            result = redisTemplate.hasKey(key);
        } catch (Exception e) {
            logger.error("redis contains error!", e);
        }
        return result;
    }

    public Object buy(final String buyer, final String id) {
//        return redisTemplate.execute(new SessionCallback<Object>() {
//            @Override
//            public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
//                redisOperations.watch((K) id);
//                Integer num = Integer.parseInt(redisTemplate.opsForValue().get(id).toString());
//                if (num > 0) {
//                    redisOperations.multi();
//                    num--;
//                    redisOperations.opsForValue().set((K) id, (V) num);
//                    logger.info("--------" + buyer + " 购买商品" + id + "成功！剩余：" + num);
//                    return redisOperations.exec();
//                } else {
//                    logger.info("--------" + buyer + " 购买商品" + id + "失败！剩余：" + num);
//                    return null;
//                }
//            }
//        });
        final CommonResult result = new CommonResult();

        return redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
                redisConnection.watch(id.getBytes());
                Integer num = Integer.parseInt(redisTemplate.opsForValue().get(id).toString());
                if (num > 0) {
                    redisConnection.multi();
                    redisConnection.set(id.getBytes(), (--num).toString().getBytes());
                    List<Object> resultList = redisConnection.exec();
                    if (resultList == null) {
                        logger.info("--------" + buyer + " 购买商品" + id + "失败！剩余：" + redisTemplate.opsForValue().get(id).toString());
                        result.setErrorCode(CommonResult.ERROR_CODE_RETRY);
                        return result;
                    }
                    logger.info("--------" + buyer + " 购买商品" + id + "成功！剩余：" + num);
                    return result;
                } else {
                    redisConnection.unwatch();
                    logger.info("--------" + buyer + " 购买商品" + id + "失败！余量不足！num = " + redisTemplate.opsForValue().get(id).toString());
                    result.setErrorCode(CommonResult.ERROR_CODE_FAILED);
                    result.setErrorMsg(" 购买商品" + id + "失败！余量不足！");
                    return result;
                }
            }
        });
    }

}
